//
//  UIModalPresentationStyleExample.swift
//  SwiftCode
//
//  Created by 于虎拴 on 2023/2/28.
//

import UIKit

class UIModalPresentationStyleExample: ListViewController {
  let tag: String
  
  init(_ tag: String = "root") {
    self.tag = tag
    super.init(nibName: nil, bundle: nil)
  }
  
  override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    self.tag = "root"
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
  }
  
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  override func getItemCount() -> Int {
    data.count
  }
  
  override func getItem(_ indexPath: IndexPath) -> Item {
    data[indexPath.row]
  }
  
  private lazy var data: [Item] = {
    var items: [Item] = [
      .init(title: "push", description: "push", action: { [weak self] in
        self?.push()
      }),
      .init(title: "dismiss", description: "dismiss", action: { [weak self] in
        self?.dismiss(animated: true)
      }),
      .init(title: "presentCustom", description: "present", action: { [weak self] in
        self?.presentCustom()
      })
    ] + UIModalPresentationStyle.allCases
      .map { style in
        Item(title: "present", description: style.debugDescription, action: {[weak self] in self?.present(style) })
      }
    return items
  }()
  
  override func viewDidLoad() {
    debugPrint(tag, #function)
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    let header = UIView()
    header.backgroundColor = .red.withAlphaComponent(0.5)
    view.addSubview(header)
    header.snp.makeConstraints { make in
      make.top.equalTo(view.safeAreaLayoutGuide)
      make.height.equalTo(48)
      make.leading.trailing.equalToSuperview()
    }
    tableView.snp.remakeConstraints { make in
      make.top.equalTo(view.safeAreaLayoutGuide).offset(48)
      make.leading.trailing.bottom.equalToSuperview()
    }
  }
  
  override func viewWillAppear(_ animated: Bool) {
    debugPrint(tag, #function, animated)
    super.viewWillAppear(animated)
  }
  
  override func viewDidAppear(_ animated: Bool) {
    debugPrint(tag, #function, animated)
    super.viewDidAppear(animated)
  }
  
  override func viewWillDisappear(_ animated: Bool) {
    debugPrint(tag, #function, animated)
    super.viewWillDisappear(animated)
  }
  
  override func viewDidDisappear(_ animated: Bool) {
    debugPrint(tag, #function, animated)
    super.viewDidDisappear(animated)
  }
  
  private func push() {
    navigationController?.pushViewController(UIModalPresentationStyleExample(tag + "-push"), animated: true)
  }
  
  private func presentCustom() {
    let tag = tag
    let viewController = UIModalPresentationStyleExample(tag + "-customPresentation")
    viewController.modalPresentationStyle = .custom
    present(viewController, draggable: true)
  }
  
  private func present(_ style: UIModalPresentationStyle = .automatic) {
    let tag = tag
    let viewController = UIModalPresentationStyleExample(tag + "-\(style)")
    viewController.modalPresentationStyle = style
    
    present(viewController, animated: true) {
      print(tag, "completion")
    }
  }
}

extension UIModalPresentationStyle: CaseIterable, CustomDebugStringConvertible {
  public static var allCases: [UIModalPresentationStyle] = [
    .fullScreen, .pageSheet, .formSheet, .currentContext, custom, .overFullScreen, .overCurrentContext, .popover, .none, .automatic
  ]
  
  public var debugDescription: String {
    switch self {
    case .fullScreen: return "fullScreen[\(rawValue)]"
    case .pageSheet: return "pageSheet[\(rawValue)]"
    case .formSheet: return "formSheet[\(rawValue)]"
    case .currentContext: return "currentContext[\(rawValue)]"
    case .custom: return "custom[\(rawValue)]"
    case .overFullScreen: return "overFullScreen[\(rawValue)]"
    case .overCurrentContext: return "overCurrentContext[\(rawValue)]"
    case .popover: return "popover[\(rawValue)]"
    case .blurOverFullScreen: return "blurOverFullScreen[\(rawValue)]"
    case .none: return "none[\(rawValue)]"
    case .automatic: return "default: automatic[\(rawValue)]"
    @unknown default:
      fatalError("unknown default")
    }
  }
}
